﻿using System;
using System.Collections.Generic;
using FNN.CustomFunctions;

namespace FNN.NetworkComponents
{
    [Serializable]
    public class Layer
    {
        private List<Neuron> _neurons;
        private int _layerId;

        /// <summary>
        ///     Конструктор по умолчанию
        /// </summary>
        public Layer()
        {
            _neurons = new List<Neuron>();
        }

        /// <summary>
        ///     Конструктор копирования
        /// </summary>
        /// <param name="source">Исходный экземпляр</param>
        public Layer(Layer source)
        {
            _layerId = source._layerId;
            _neurons = new List<Neuron>();
            foreach (var neuron in source._neurons)
            {
                _neurons.Add(new Neuron(neuron));
            }
        }

        /// <summary>
        ///     Конструктор с параметрами
        /// </summary>
        /// <param name="layerId">Идентификатор слоя</param>
        /// <param name="layerSize">Размер слоя</param>
        /// <param name="isFirstOrLast">Является первым или последним слоем</param>
        /// <param name="functions">Активационные функции</param>
        public Layer(int layerId, int layerSize, bool isFirstOrLast, List<FunctionTypes> functions = null)
        {
            _layerId = layerId;
            var randomizer = new Random();
            _neurons = new List<Neuron>();

            if (functions == null)
            {
                functions = new List<FunctionTypes> {FunctionTypes.NotDefined};
            }

            for (var i = 0; i < layerSize; i++)
            {
                var functionIndex = randomizer.Next(0, (functions.Count - 1));
                _neurons.Add((isFirstOrLast) ? new Neuron() {NeuronId =  _layerId * 1000 + i} : new Neuron(functions[functionIndex]) {NeuronId = _layerId * 1000 + i});
            }
        }

        /// <summary>
        ///     Список нейронов слоя
        /// </summary>
        public List<Neuron> Neurons
        {
            get { return _neurons; }
            set { _neurons = value; }
        }

        /// <summary>
        ///     Идентификатор слоя
        /// </summary>
        public int LayerId
        {
            get { return _layerId; }
            set { _layerId = value; }
        }
    }
}